﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using TyNetCoreBlog.Helpers;
using TyNetCoreBlog.Models.Data;
using TyNetCoreBlog.Models.Dto.Blog;
using TyNetCoreBlog.Repository.RepositoryWrapper;
using static TyNetCoreBlog.Helpers.ResponseMsg;

namespace TyNetCoreBlog.Controllers
{
    [Route("api/blogs")]
    [EnableCors("any")]
    [ApiController]
    public class BlogsController : ControllerBase
    {
        private readonly AppDbContext _dbContext;
        private readonly IRepositoryWrapper _repositoryWrapper;
        private readonly IMapper _mapper;

        // 默认条数
        private const int DefaultTopNum = 6;

        public BlogsController(AppDbContext dbContext, IRepositoryWrapper repositoryWrapper, IMapper mapper)
        {
            _dbContext = dbContext;
            this._repositoryWrapper = repositoryWrapper ?? throw new ArgumentNullException(nameof(repositoryWrapper));
            this._mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
        }


        /// <summary>
        /// 分页获取博客列表
        /// </summary>
        /// <returns></returns>
        [HttpGet(Name = nameof(GetBlogs))]
        [ResponseCache(Duration = 15)]
        public async Task<ActionResult<IEnumerable<BlogDto>>> GetBlogs([FromQuery] BlogResourceParameters parameters)
        {
            var pagedlist = await _repositoryWrapper.Blog.GetAllAsync(parameters);
            // 分页元数据
            var paginationMetadata = new
            {
                totalCoun = pagedlist.TotalCount,
                pageSize = pagedlist.PageSize,
                currentPage = pagedlist.CurrentPage,
                totalPages = pagedlist.TotalPages,
                // 前一页链接
                previousePageLink = pagedlist.HasPrevious ? Url.Link(nameof(GetBlogs), new
                {
                    pageNum = pagedlist.CurrentPage - 1,
                    pageSize = pagedlist.PageSize,
                    keywords = parameters.Keywords
                }) : null,
                // 后一页链接
                nextPageLink = pagedlist.HasNext ? Url.Link(nameof(GetBlogs), new
                {
                    pageNum = pagedlist.CurrentPage + 1,
                    pageSize = pagedlist.PageSize,
                    keywords = parameters.Keywords
                }) : null
            };

            Response.Headers.Add("X-Pagination", JsonConvert.SerializeObject(paginationMetadata));
            var blogDtoList = _mapper.Map<IEnumerable<BlogDto>>(pagedlist).ToList();
            return Ok(new { status = 200, message = "成功", data = blogDtoList, total = pagedlist.TotalCount });
        }


        /// <summary>
        /// 获取博客前几条
        /// </summary>
        /// <param name="topNum">条数</param>
        /// <returns></returns>
        [HttpGet]
        [Route("top/{topNum}")]
        [ResponseCache(Duration = 15)]
        public async Task<ActionResult<IEnumerable<BlogDto>>> GetTopBlogs(int topNum)
        {
            if (topNum < 1 || topNum > 15)
            {
                topNum = DefaultTopNum;
            }
            var blogs = await _repositoryWrapper.Blog.GetTopBlogs(topNum);
            var blogDtoList = _mapper.Map<IEnumerable<BlogDto>>(blogs);
            return Ok(new ResponseMsg(ApiStatus.OK, blogDtoList));
        }


        /// <summary>
        /// 获取热门博客
        /// </summary>
        /// <param name="topNum"></param>
        /// <returns></returns>
        [HttpGet]
        [Route("hot/{topNum}")]
        [ResponseCache(Duration = 15)]
        public async Task<ActionResult<IEnumerable<BlogDto>>> GetHotBlogs(int topNum)
        {
            if (topNum < 1 || topNum > 15)
            {
                topNum = DefaultTopNum;
            }
            var blogs = await _repositoryWrapper.Blog.GetHotBlogs(topNum);
            var blogDtoList = _mapper.Map<IEnumerable<BlogDto>>(blogs);
            return Ok(new ResponseMsg(ApiStatus.OK, blogDtoList));
        }



        /// <summary>
        /// 获取博客详情
        /// </summary>
        /// <param name="blogId"></param>
        /// <returns></returns>
        [HttpGet]
        [Route("{blogId}", Name = nameof(GetBlogDetail))]
        [ResponseCache(Duration = 15)]
        public async Task<ActionResult<BlogDto>> GetBlogDetail(int blogId)
        {
            var blog = await _repositoryWrapper.Blog.GetByIdAsync(blogId);
            if (blog == null)
            {
                return NotFound(new ResponseMsg(ApiStatus.NotFound));
            }
            // 更新浏览量
            _dbContext.Blogs.Attach(blog);
            blog.Views += 1;
            _dbContext.SaveChanges();
            var blogDto = _mapper.Map<BlogDto>(blog);
            return Ok(new ResponseMsg(ApiStatus.OK, blogDto));
        }


        /// <summary>
        /// 博客归档
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Route("archive")]
        [ResponseCache(Duration = 15)]
        public async Task<ActionResult<Dictionary<int, IEnumerable<BlogDto>>>> GetBlogArchive()
        {
            var years = await _repositoryWrapper.Blog.GetYearsAsync();
            var archive = await _repositoryWrapper.Blog.BlogArchiveAsync(years);
            var archiveDto = _mapper.Map<Dictionary<int, IEnumerable<BlogDto>>>(archive);
            return Ok(new ResponseMsg(ApiStatus.OK, archiveDto));
        }


    }
}
